﻿#include <stdio.h>
#include <stdlib.h>

#include "map.h"

// 创建一个新的 Map
Map *CreateMap(int size)
{
    Map *map = (Map *)malloc(sizeof(Map));
    if (map == NULL)
    {
        perror("Error: unable to allocate memory for new map.");
        exit(EXIT_FAILURE);
    }
    map->size = size;
    map->buckets = (Node **)calloc(size, sizeof(Node *));
    if (map->buckets == NULL)
    {
        perror("Error: unable to allocate memory for buckets.");
        exit(EXIT_FAILURE);
    }
    return map;
}

// 删除一个 Map
void DeleteMap(Map *map)
{
    for (int i = 0; i < map->size; ++i)
    {
        Node *node = map->buckets[i];
        while (node != NULL)
        {
            Node *tmp = node;
            node = node->next;
            deleteNode(tmp);
        }
    }
    free(map->buckets);
    free(map);
}

// 添加键值对
void Put(Map *map, uint key, void *value)
{
    int idx = hash(key, map->size);
    Node *node = map->buckets[idx];
    while (node != NULL)
    {
        if (node->key == key)
        {
            node->value = value;
            return;
        }
        node = node->next;
    }
    node = createNode(key, value);
    node->next = map->buckets[idx];
    map->buckets[idx] = node;
}

// 获取键对应的值，如果不存在则返回 NULL
void *Get(Map *map, uint key)
{
    int idx = hash(key, map->size);
    Node *node = map->buckets[idx];
    while (node != NULL)
    {
        if (node->key == key)
            return node->value;
        node = node->next;
    }
    return NULL;
}

// 创建一个新的迭代器
Iterator *CreateIterator(Map *map)
{
    Iterator *it = (Iterator *)malloc(sizeof(Iterator));
    if (it == NULL)
    {
        perror("Error: unable to allocate memory for new iterator.");
        exit(EXIT_FAILURE);
    }
    it->map = map;
    it->bucket_idx = 0;
    it->node = NULL;
    return it;
}

// 删除一个迭代器
void DeleteIterator(Iterator *it)
{
    free(it);
}

// 将迭代器移动到下一个键值对，并返回该键值对的指针
Node *GetNextNode(Iterator *it)
{
    bool isCurBucketFirstNode = true;
    while (1)
    {
        if (it->bucket_idx >= it->map->size)
        {
            // 所有桶已经遍历完成。
            return NULL;
        }

        if (it->map->buckets[it->bucket_idx] == NULL) // 当前桶为空桶
        {
        next_blucket:
            it->bucket_idx++;
            it->node = NULL;
            isCurBucketFirstNode = true;
            continue;
        }
        else
        {
            if (it->node == NULL && isCurBucketFirstNode) // 当前桶还没开始遍历，第一次进入当前桶。
            {
                it->node = it->map->buckets[it->bucket_idx];
                isCurBucketFirstNode = false;
            }
            else // 当前桶继续垂直遍历。
            {
                it->node = it->node->next;
            }

            if (it->node == NULL) // 当前桶遍历完了，那next node就应该去下一个桶里找了。
            {

                goto next_blucket;
            }
            return it->node;
        }
    }
}

// 创建一个新的节点
Node *createNode(uint key, void *value)
{
    Node *node = (Node *)malloc(sizeof(Node));
    if (node == NULL)
    {
        perror("Error: unable to allocate memory for new node.");
        exit(EXIT_FAILURE);
    }
    node->key = key;
    node->value = value;
    node->next = NULL;
    return node;
}

// 删除一个节点
void deleteNode(Node *node)
{
    free(node);
}

// 计算哈希值
int hash(uint key, int size)
{
    int hash = 0;
    hash = 31 * hash + key;
    return abs(hash % size);
}